0.1 What is Data Visualization ?

Data visualization is the representation of data or information in a graph, chart, or other visual format. It communicates relationships of the data with images. This is important because it allows trends and patterns to be more easily seen.With the rise of big data upon us, we need to be able to interpret increasingly larger batches of data. Machine learning makes it easier to conduct analyses such as predictive analysis, which can then serve as helpful visualizations to present.

0.2 How is data visualization used ?

Data visualization has many uses. Each type of data visualization can be used in different ways.

Changes over time

This is the most basic and common uses of data visualization as most data has an element of time involved. Therefore, the first step in a lot of data analyses is to see how the data trends over time.

Examining a network

An example of this is market research. Marketing professionals need to know which audiences to target with their message, so they analyze the entire market to identify audience clusters, bridges between the clusters, influencers withing clusters, and outliers.

Scheduling

When planning out a schedule or timeline for a complex project, things can get confusing. A Gantt chart solves that issue by clearly illustrating each task within the project and how long it will take to complete.

Analyzing value and risk

Determining complex metrics such as value and risk requires many different variables to be factored in, making it almost impossible to see accurately with a plain spreadsheet. Data visualization can be as simple as color-coding a formula to show which opportunities are valuable and which are risky.

0.3 Types of Data visualization

So now we will go through each type of data visualization charts with example.

[for the example part we will use ggplot2 function we will describe about it later]

Line Chart

A line chart illustrates over time. The x-axis is usually a period of time, while the y-axis is quantity. So, this could illustrate a company’s sales for the year broken down by month or how many units a factory produced each day for the past week.

For the example section, let’s consider a dataset composed of 3 columns: * Year * Name of baby selected according to year

With the line chart we will try to find out which Amerian baby names was popular in previous 30 years.

The libraries and functions we are using here to show the examples is pretty much advance knowledge we will describe in details about these later part of this document.

library(babynames) # Provide the dataset: a dataframe called babynames
library(dplyr)
library(hrbrthemes)
library(viridis) #for the color pallete and color scales 
## Loading required package: viridisLite
#keep only 3 names 
name <- babynames %>% 
  filter(name %in% c("Monica", "Victoria", "Rachel")) %>%
  filter(sex=="F")

#plot 
name %>% 
    ggplot( aes(x=year, y=n, group=name, color=name)) +
    geom_line() +
    scale_color_viridis(discrete = TRUE) +
    ggtitle("Popularity of American names in the previous 30 years") +
    theme_ipsum() +
    ylab("Number of babies born")

So here we can get some interesting insight about the names that has been used in America with line chart. We can see here “Rachel” is the winner.

Area Chart

An area chart is an adaptation of a line chart where the area under the line is filled in to emphasize its significance. The color fill for the area under each line should be somewhat transparent so that overlapping areas can be discerned.

Now for the example of area chart we will create a dataset and implement area chart on that.

library(viridis)
library(hrbrthemes)
#creating dataset 
time <- as.numeric(rep(seq(1,7), each = 7))
value <- runif(49,10,100)
group <- rep(LETTERS[1:7], times = 7)
data <- data.frame(time, value, group)

#simple implementation
ggplot(data, aes(x = time, y = value, fill = group))+
  geom_area()

#sorting levels alphabetically 
mylevels <- levels(data$group)
data$group <- factor(data$group, levels = sort(mylevels))

#sort following values at time = 5
mylevels <- data %>% 
  filter(time == 6) %>% 
  arrange(value)
data$group <- factor(data$group, levels = mylevels$group)
#compute percentage using dplyr for proportional stacked chart 
#In a proportional stacked area graph, the sum of each year is always equal to hundred and value of each group is represented through percentages. 
data <- data %>% 
  group_by(time,group) %>% 
  summarise(n = sum(value)) %>% 
  mutate(percentage = n / sum(n))
## `summarise()` regrouping output by 'time' (override with `.groups` argument)
#plot
ggplot(data , aes(x = time, y = value, fill = group))+
  geom_area(alpha = 0.6, size = .5, color = "white")+
  scale_fill_viridis(discrete = T)+
  theme_ipsum()+
  ggtitle("The race between .....")

This is the representaion of area chart. The first chart is a simple implementation and last one is a bit advance one using theme.

Bar chart

A bar chart also illustrates changes over time. But if there is more than one variable, a bar chart can make it easier to compare the data for each variable at each moment in time. For example, a bar chart could compare the company’s sales from this year to last year.

For the example we will use a dataset showing the quantity of weapons exported by the top 20 largest exporters in 2017

library(tidyverse)
## ── Attaching packages ──────────────
## ✓ tibble  3.0.3     ✓ purrr   0.3.4
## ✓ tidyr   1.1.1     ✓ stringr 1.4.0
## ✓ readr   1.3.1     ✓ forcats 0.5.0
## Warning: package 'tibble' was built under R version 3.6.2
## Warning: package 'tidyr' was built under R version 3.6.2
## Warning: package 'purrr' was built under R version 3.6.2
## ── Conflicts ───────────────────────
## x dplyr::filter() masks plotly::filter(), stats::filter()
## x dplyr::lag()    masks stats::lag()
library(hrbrthemes)
library(kableExtra)
## 
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows
options(knitr.table.format = "html")

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/7_OneCatOneNum.csv", header=TRUE, sep=",")

# Barplot
data %>%
  filter(!is.na(Value)) %>%
  arrange(Value) %>%
  tail(20) %>%
  mutate(Country=factor(Country, Country)) %>%
  ggplot( aes(x=Country, y=Value) ) +
    geom_bar(stat="identity", fill="#69b3a2") +
    coord_flip() +
    theme_ipsum() +
    theme(
      panel.grid.minor.y = element_blank(),
      panel.grid.major.y = element_blank(),
      legend.position="none"
    ) +
    xlab("") +
    ylab("Weapon quantity (SIPRI trend-indicator value)")

Another type of example can be for creating stacked bar chart. We will use MPAA rating to differentiate movie type according to genre.

We will use three MPAA rating system: R - Restricted (Contains some adult material. Parents are urged to learn more about the film before taking their young children with them.)

PG-13 - Parents Strongly Cautioned (Parents are urged to be cautious. Some material may be inappropiate for pre-teenagers.)

PG - Parental Guidance Suggested (Parents urged to give “parental guidance.” May contain some material parents might not like for their young children)

# for reproducibility
set.seed(123)
library(ggplot2)
library(ggstatsplot)
## Warning: package 'ggstatsplot' was built under R version 3.6.2
## Registered S3 method overwritten by 'broom.mixed':
##   method      from 
##   tidy.gamlss broom
## Registered S3 methods overwritten by 'lme4':
##   method                          from
##   cooks.distance.influence.merMod car 
##   influence.merMod                car 
##   dfbeta.influence.merMod         car 
##   dfbetas.influence.merMod        car
## In case you would like cite this package, cite it as:
##      Patil, I. (2018). ggstatsplot: "ggplot2" Based Plots with Statistical Details. CRAN.
##      Retrieved from https://cran.r-project.org/web/packages/ggstatsplot/index.html
# plot
ggstatsplot::ggbarstats(
  data = ggstatsplot::movies_long,
  x = mpaa,
  y = genre,
  sampling.plan = "jointMulti",
  title = "MPAA Ratings by Genre",
  xlab = "movie genre",
  legend.title = "MPAA rating",
  ggtheme = hrbrthemes::theme_ipsum(),
  ggplot.component = list(scale_x_discrete(guide = guide_axis(n.dodge = 2))),
  palette = "Set2",
  messages = FALSE
)

So, from here we can say that Drama genre is more restricted than any other genre.

Histogram

A histogram looks like a bar chart, but measures frequency rather than trends over time.It is an accurate graphical representation of the distribution of a numeric variable. It takes as input numeric variables only. The variable is cut into several bins, and the number of observation per bin is represented by the height of the bar. The x-axis of a histogram lists the “bins” or intervals of the variable, and the y-axis is frequency, so each bar represents the frequency of that bin. For example, you could measure the frequencies of each answer to a survey question. The bins would be the answer: “unsatisfactory,” “neutral,” and “satisfactory.” This would tell you how many people gave each answer.

Here is an example showing the distribution of the night price of Rbnb appartements in the south of France. Price range is divided per 10 euros interval. For example, there are slightly less than 750 appartements with a night price between 100 and 110 euros.

# Libraries
library(tidyverse)
library(hrbrthemes)
library(viridis)

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/1_OneNum.csv", header=TRUE)

# Make the histogram
data %>%
  filter( price<300 ) %>%
  ggplot( aes(x=price)) +
    stat_bin(breaks=seq(0,300,10), fill="#69b3a2", color="#e9ecef", alpha=0.9) +
    ggtitle("Night price distribution of Airbnb appartements") +
    theme_ipsum()

This is a very basic yet very insightful example of how histogram can give such insights.

Scatter Plot

Scatter plots are used to find correlations. Each point on a scatter plot means “when x = this, then y equals this.” That way, if the points trend a certain way (upward to the left, downward to the right, etc.) there is a relationship between them. If the plot is truly scattered with no trend at all, then the variables do not affect each other at all.

For example we will see evolution of bitcoin on april 2018:

# Libraries
library(ggplot2)
library(dplyr)
library(hrbrthemes)

# Load dataset from github
data <- read.table("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered.csv", header=T)

data$date <- as.Date(data$date)

# Plot
data %>%
  tail(10) %>%
  ggplot( aes(x=date, y=value)) +
    geom_line( color="grey") +
    geom_point(shape=21, color="red", fill="#69b3a2", size=6) +
    theme_ipsum() +
    ggtitle("Evolution of bitcoin price")

Map

## Warning: package 'sf' was built under R version 3.6.2
## Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
## Warning: package 'raster' was built under R version 3.6.2
## Loading required package: sp
## Warning: package 'sp' was built under R version 3.6.2
## 
## Attaching package: 'raster'
## The following object is masked from 'package:tidyr':
## 
##     extract
## The following object is masked from 'package:dplyr':
## 
##     select
## The following object is masked from 'package:plotly':
## 
##     select
## Warning: package 'spData' was built under R version 3.6.2
vignette(package = "sf") # see which vignettes are available
vignette("sf1")          # an introduction to the package
## starting httpd help server ... done
names(world)
##  [1] "iso_a2"    "name_long" "continent" "region_un" "subregion" "type"     
##  [7] "area_km2"  "pop"       "lifeExp"   "gdpPercap" "geom"
plot(world)

Making map using R:

## Warning: package 'tmap' was built under R version 3.6.2
## tmap mode set to interactive viewing

So these are few examples of visualizing data.

LS0tCnRpdGxlOiAiRGF0YSBWaXN1YWxpemF0aW9uIgphdXRob3I6ICJTb2Z0YW5iZWVzIFRlY2hub2xvZ2llcyBQdnQuIEx0ZCIKZGF0ZTogIjExLzMvMjAyMCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHVuaXRlZAogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogICAgY3NzOiBzdHlsZXMuY3NzCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBmaWdfd2lkdGg6IDExCiAgICBmaWdfaGVpZ2h0OiAxMAotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwbG90bHkpCmxpYnJhcnkoZHBseXIpCgpgYGAKCgojIyBXaGF0IGlzIERhdGEgVmlzdWFsaXphdGlvbiA/IHsjZGl2MX0KRGF0YSB2aXN1YWxpemF0aW9uIGlzIHRoZSByZXByZXNlbnRhdGlvbiBvZiBkYXRhIG9yIGluZm9ybWF0aW9uIGluIGEgZ3JhcGgsIGNoYXJ0LCBvciBvdGhlciB2aXN1YWwgZm9ybWF0LiBJdCBjb21tdW5pY2F0ZXMgcmVsYXRpb25zaGlwcyBvZiB0aGUgZGF0YSB3aXRoIGltYWdlcy4gVGhpcyBpcyBpbXBvcnRhbnQgYmVjYXVzZSBpdCBhbGxvd3MgdHJlbmRzIGFuZCBwYXR0ZXJucyB0byBiZSBtb3JlIGVhc2lseSBzZWVuLldpdGggdGhlIHJpc2Ugb2YgYmlnIGRhdGEgdXBvbiB1cywgd2UgbmVlZCB0byBiZSBhYmxlIHRvIGludGVycHJldCBpbmNyZWFzaW5nbHkgbGFyZ2VyIGJhdGNoZXMgb2YgZGF0YS4gTWFjaGluZSBsZWFybmluZyBtYWtlcyBpdCBlYXNpZXIgdG8gY29uZHVjdCBhbmFseXNlcyBzdWNoIGFzIHByZWRpY3RpdmUgYW5hbHlzaXMsIHdoaWNoIGNhbiB0aGVuIHNlcnZlIGFzIGhlbHBmdWwgdmlzdWFsaXphdGlvbnMgdG8gcHJlc2VudC4KCiMjIEhvdyBpcyBkYXRhIHZpc3VhbGl6YXRpb24gdXNlZCA/IHsjZGl2MX0KRGF0YSB2aXN1YWxpemF0aW9uIGhhcyBtYW55IHVzZXMuIEVhY2ggdHlwZSBvZiBkYXRhIHZpc3VhbGl6YXRpb24gY2FuIGJlIHVzZWQgaW4gZGlmZmVyZW50IHdheXMuIAoKCjo6OmNoYW5nZQo6Ojp7I3RpdGxlfQoqKkNoYW5nZXMgb3ZlciB0aW1lKioKOjo6OgpUaGlzIGlzIHRoZSBtb3N0IGJhc2ljIGFuZCBjb21tb24gdXNlcyBvZiBkYXRhIHZpc3VhbGl6YXRpb24gYXMgbW9zdCBkYXRhIGhhcyBhbiBlbGVtZW50IG9mIHRpbWUgaW52b2x2ZWQuIFRoZXJlZm9yZSwgdGhlIGZpcnN0IHN0ZXAgaW4gYSBsb3Qgb2YgZGF0YSBhbmFseXNlcyBpcyB0byBzZWUgaG93IHRoZSBkYXRhIHRyZW5kcyBvdmVyIHRpbWUuICAKOjo6Cgo6OjpuZXR3b3JrCjo6OnsjdGl0bGV9CioqRXhhbWluaW5nIGEgbmV0d29yayoqCjo6OjoKQW4gZXhhbXBsZSBvZiB0aGlzIGlzIG1hcmtldCByZXNlYXJjaC4gTWFya2V0aW5nIHByb2Zlc3Npb25hbHMgbmVlZCB0byBrbm93IHdoaWNoIGF1ZGllbmNlcyB0byB0YXJnZXQgd2l0aCB0aGVpciBtZXNzYWdlLCBzbyB0aGV5IGFuYWx5emUgdGhlIGVudGlyZSBtYXJrZXQgdG8gaWRlbnRpZnkgYXVkaWVuY2UgY2x1c3RlcnMsIGJyaWRnZXMgYmV0d2VlbiB0aGUgY2x1c3RlcnMsIGluZmx1ZW5jZXJzIHdpdGhpbmcgY2x1c3RlcnMsIGFuZCBvdXRsaWVycy4gICAKOjo6Cgo6OjpzY2hlZHVsaW5nCjo6OnsjdGl0bGV9CioqU2NoZWR1bGluZyoqCjo6OjoKV2hlbiBwbGFubmluZyBvdXQgYSBzY2hlZHVsZSBvciB0aW1lbGluZSBmb3IgYSBjb21wbGV4IHByb2plY3QsIHRoaW5ncyBjYW4gZ2V0IGNvbmZ1c2luZy4gQSBHYW50dCBjaGFydCBzb2x2ZXMgdGhhdCBpc3N1ZSBieSBjbGVhcmx5IGlsbHVzdHJhdGluZyBlYWNoIHRhc2sgd2l0aGluIHRoZSBwcm9qZWN0IGFuZCBob3cgbG9uZyBpdCB3aWxsIHRha2UgdG8gY29tcGxldGUuICAgCjo6OgoKOjo6YW5hbHl6ZQo6Ojp7I3RpdGxlfQoqKkFuYWx5emluZyB2YWx1ZSBhbmQgcmlzayoqCjo6OjoKRGV0ZXJtaW5pbmcgY29tcGxleCBtZXRyaWNzIHN1Y2ggYXMgdmFsdWUgYW5kIHJpc2sgcmVxdWlyZXMgbWFueSBkaWZmZXJlbnQgdmFyaWFibGVzIHRvIGJlIGZhY3RvcmVkIGluLCBtYWtpbmcgaXQgYWxtb3N0IGltcG9zc2libGUgdG8gc2VlIGFjY3VyYXRlbHkgd2l0aCBhIHBsYWluIHNwcmVhZHNoZWV0LiBEYXRhIHZpc3VhbGl6YXRpb24gY2FuIGJlIGFzIHNpbXBsZSBhcyBjb2xvci1jb2RpbmcgYSBmb3JtdWxhIHRvIHNob3cgd2hpY2ggb3Bwb3J0dW5pdGllcyBhcmUgdmFsdWFibGUgYW5kIHdoaWNoIGFyZSByaXNreS4gICAKOjo6CgoKIyMgVHlwZXMgb2YgRGF0YSB2aXN1YWxpemF0aW9uIHsjZGl2MX0KU28gbm93IHdlIHdpbGwgZ28gdGhyb3VnaCBlYWNoIHR5cGUgb2YgZGF0YSB2aXN1YWxpemF0aW9uIGNoYXJ0cyB3aXRoIGV4YW1wbGUuIAoKW2ZvciB0aGUgZXhhbXBsZSBwYXJ0IHdlIHdpbGwgdXNlIGdncGxvdDIgZnVuY3Rpb24gd2Ugd2lsbCBkZXNjcmliZSBhYm91dCBpdCBsYXRlcl0KCjo6OnsjbGluZWNoYXJ0fQo6Ojp7I2NoYXJ0dGl0bGV9CioqTGluZSBDaGFydCoqCjo6OgpBIGxpbmUgY2hhcnQgaWxsdXN0cmF0ZXMgb3ZlciB0aW1lLiBUaGUgeC1heGlzIGlzIHVzdWFsbHkgYSBwZXJpb2Qgb2YgdGltZSwgd2hpbGUgdGhlIHktYXhpcyBpcyBxdWFudGl0eS4gU28sIHRoaXMgY291bGQgaWxsdXN0cmF0ZSBhIGNvbXBhbnkncyBzYWxlcyBmb3IgdGhlIHllYXIgYnJva2VuIGRvd24gYnkgbW9udGggb3IgaG93IG1hbnkgdW5pdHMgYSBmYWN0b3J5IHByb2R1Y2VkIGVhY2ggZGF5IGZvciB0aGUgcGFzdCB3ZWVrLiAKCkZvciB0aGUgZXhhbXBsZSBzZWN0aW9uLCBsZXQncyBjb25zaWRlciBhIGRhdGFzZXQgY29tcG9zZWQgb2YgMyBjb2x1bW5zOgoqIFllYXIKKiBOYW1lIG9mIGJhYnkgc2VsZWN0ZWQgYWNjb3JkaW5nIHRvIHllYXIgCgpXaXRoIHRoZSBsaW5lIGNoYXJ0IHdlIHdpbGwgdHJ5IHRvIGZpbmQgb3V0IHdoaWNoIEFtZXJpYW4gYmFieSBuYW1lcyB3YXMgcG9wdWxhciBpbiBwcmV2aW91cyAzMCB5ZWFycy4KCjo6Om5vdGVzClRoZSBsaWJyYXJpZXMgYW5kIGZ1bmN0aW9ucyB3ZSBhcmUgdXNpbmcgaGVyZSB0byBzaG93IHRoZSBleGFtcGxlcyBpcyBwcmV0dHkgbXVjaCBhZHZhbmNlIGtub3dsZWRnZSB3ZSB3aWxsIGRlc2NyaWJlIGluIGRldGFpbHMgYWJvdXQgdGhlc2UgbGF0ZXIgcGFydCBvZiB0aGlzIGRvY3VtZW50Lgo6OjoKCmBgYHtyfQpsaWJyYXJ5KGJhYnluYW1lcykgIyBQcm92aWRlIHRoZSBkYXRhc2V0OiBhIGRhdGFmcmFtZSBjYWxsZWQgYmFieW5hbWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoaHJicnRoZW1lcykKbGlicmFyeSh2aXJpZGlzKSAjZm9yIHRoZSBjb2xvciBwYWxsZXRlIGFuZCBjb2xvciBzY2FsZXMgCgoja2VlcCBvbmx5IDMgbmFtZXMgCm5hbWUgPC0gYmFieW5hbWVzICU+JSAKICBmaWx0ZXIobmFtZSAlaW4lIGMoIk1vbmljYSIsICJWaWN0b3JpYSIsICJSYWNoZWwiKSkgJT4lCiAgZmlsdGVyKHNleD09IkYiKQoKI3Bsb3QgCm5hbWUgJT4lIAogICAgZ2dwbG90KCBhZXMoeD15ZWFyLCB5PW4sIGdyb3VwPW5hbWUsIGNvbG9yPW5hbWUpKSArCiAgICBnZW9tX2xpbmUoKSArCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSkgKwogICAgZ2d0aXRsZSgiUG9wdWxhcml0eSBvZiBBbWVyaWNhbiBuYW1lcyBpbiB0aGUgcHJldmlvdXMgMzAgeWVhcnMiKSArCiAgICB0aGVtZV9pcHN1bSgpICsKICAgIHlsYWIoIk51bWJlciBvZiBiYWJpZXMgYm9ybiIpCmBgYApTbyBoZXJlIHdlIGNhbiBnZXQgc29tZSBpbnRlcmVzdGluZyBpbnNpZ2h0IGFib3V0IHRoZSBuYW1lcyB0aGF0IGhhcyBiZWVuIHVzZWQgaW4gQW1lcmljYSB3aXRoIGxpbmUgY2hhcnQuIFdlIGNhbiBzZWUgaGVyZSAiUmFjaGVsIiBpcyB0aGUgd2lubmVyLiAKOjo6Cgo6Ojp7I2FyZWFjaGFydH0KOjo6eyNjaGFydHRpdGxlfQoqKkFyZWEgQ2hhcnQqKgo6OjoKQW4gYXJlYSBjaGFydCBpcyBhbiBhZGFwdGF0aW9uIG9mIGEgbGluZSBjaGFydCB3aGVyZSB0aGUgYXJlYSB1bmRlciB0aGUgbGluZSBpcyBmaWxsZWQgaW4gdG8gZW1waGFzaXplIGl0cyBzaWduaWZpY2FuY2UuIFRoZSBjb2xvciBmaWxsIGZvciB0aGUgYXJlYSB1bmRlciBlYWNoIGxpbmUgc2hvdWxkIGJlIHNvbWV3aGF0IHRyYW5zcGFyZW50IHNvIHRoYXQgb3ZlcmxhcHBpbmcgYXJlYXMgY2FuIGJlIGRpc2Nlcm5lZC4KCk5vdyBmb3IgdGhlIGV4YW1wbGUgb2YgYXJlYSBjaGFydCB3ZSB3aWxsIGNyZWF0ZSBhIGRhdGFzZXQgYW5kIGltcGxlbWVudCBhcmVhIGNoYXJ0IG9uIHRoYXQuCmBgYHtyfQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoaHJicnRoZW1lcykKI2NyZWF0aW5nIGRhdGFzZXQgCnRpbWUgPC0gYXMubnVtZXJpYyhyZXAoc2VxKDEsNyksIGVhY2ggPSA3KSkKdmFsdWUgPC0gcnVuaWYoNDksMTAsMTAwKQpncm91cCA8LSByZXAoTEVUVEVSU1sxOjddLCB0aW1lcyA9IDcpCmRhdGEgPC0gZGF0YS5mcmFtZSh0aW1lLCB2YWx1ZSwgZ3JvdXApCgojc2ltcGxlIGltcGxlbWVudGF0aW9uCmdncGxvdChkYXRhLCBhZXMoeCA9IHRpbWUsIHkgPSB2YWx1ZSwgZmlsbCA9IGdyb3VwKSkrCiAgZ2VvbV9hcmVhKCkKCiNzb3J0aW5nIGxldmVscyBhbHBoYWJldGljYWxseSAKbXlsZXZlbHMgPC0gbGV2ZWxzKGRhdGEkZ3JvdXApCmRhdGEkZ3JvdXAgPC0gZmFjdG9yKGRhdGEkZ3JvdXAsIGxldmVscyA9IHNvcnQobXlsZXZlbHMpKQoKI3NvcnQgZm9sbG93aW5nIHZhbHVlcyBhdCB0aW1lID0gNQpteWxldmVscyA8LSBkYXRhICU+JSAKICBmaWx0ZXIodGltZSA9PSA2KSAlPiUgCiAgYXJyYW5nZSh2YWx1ZSkKZGF0YSRncm91cCA8LSBmYWN0b3IoZGF0YSRncm91cCwgbGV2ZWxzID0gbXlsZXZlbHMkZ3JvdXApCiNjb21wdXRlIHBlcmNlbnRhZ2UgdXNpbmcgZHBseXIgZm9yIHByb3BvcnRpb25hbCBzdGFja2VkIGNoYXJ0IAojSW4gYSBwcm9wb3J0aW9uYWwgc3RhY2tlZCBhcmVhIGdyYXBoLCB0aGUgc3VtIG9mIGVhY2ggeWVhciBpcyBhbHdheXMgZXF1YWwgdG8gaHVuZHJlZCBhbmQgdmFsdWUgb2YgZWFjaCBncm91cCBpcyByZXByZXNlbnRlZCB0aHJvdWdoIHBlcmNlbnRhZ2VzLiAKZGF0YSA8LSBkYXRhICU+JSAKICBncm91cF9ieSh0aW1lLGdyb3VwKSAlPiUgCiAgc3VtbWFyaXNlKG4gPSBzdW0odmFsdWUpKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnRhZ2UgPSBuIC8gc3VtKG4pKQoKI3Bsb3QKZ2dwbG90KGRhdGEgLCBhZXMoeCA9IHRpbWUsIHkgPSB2YWx1ZSwgZmlsbCA9IGdyb3VwKSkrCiAgZ2VvbV9hcmVhKGFscGhhID0gMC42LCBzaXplID0gLjUsIGNvbG9yID0gIndoaXRlIikrCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVCkrCiAgdGhlbWVfaXBzdW0oKSsKICBnZ3RpdGxlKCJUaGUgcmFjZSBiZXR3ZWVuIC4uLi4uIikKCgpgYGAKClRoaXMgaXMgdGhlIHJlcHJlc2VudGFpb24gb2YgYXJlYSBjaGFydC4gVGhlIGZpcnN0IGNoYXJ0IGlzIGEgc2ltcGxlIGltcGxlbWVudGF0aW9uIGFuZCBsYXN0IG9uZSBpcyBhIGJpdCBhZHZhbmNlIG9uZSB1c2luZyB0aGVtZS4gCjo6OgoKOjo6eyNhcmVhY2hhcnR9Cjo6OnsjY2hhcnR0aXRsZX0KKipCYXIgY2hhcnQqKgo6OjoKQSBiYXIgY2hhcnQgYWxzbyBpbGx1c3RyYXRlcyBjaGFuZ2VzIG92ZXIgdGltZS4gQnV0IGlmIHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgdmFyaWFibGUsIGEgYmFyIGNoYXJ0IGNhbiBtYWtlIGl0IGVhc2llciB0byBjb21wYXJlIHRoZSBkYXRhIGZvciBlYWNoIHZhcmlhYmxlIGF0IGVhY2ggbW9tZW50IGluIHRpbWUuIEZvciBleGFtcGxlLCBhIGJhciBjaGFydCBjb3VsZCBjb21wYXJlIHRoZSBjb21wYW554oCZcyBzYWxlcyBmcm9tIHRoaXMgeWVhciB0byBsYXN0IHllYXIuCgpGb3IgdGhlIGV4YW1wbGUgd2Ugd2lsbCB1c2UgYSBkYXRhc2V0IHNob3dpbmcgdGhlIHF1YW50aXR5IG9mIHdlYXBvbnMgZXhwb3J0ZWQgYnkgdGhlIHRvcCAyMCBsYXJnZXN0IGV4cG9ydGVycyBpbiAyMDE3CgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoaHJicnRoZW1lcykKbGlicmFyeShrYWJsZUV4dHJhKQpvcHRpb25zKGtuaXRyLnRhYmxlLmZvcm1hdCA9ICJodG1sIikKCiMgTG9hZCBkYXRhc2V0IGZyb20gZ2l0aHViCmRhdGEgPC0gcmVhZC50YWJsZSgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2hvbHR6eS9kYXRhX3RvX3Zpei9tYXN0ZXIvRXhhbXBsZV9kYXRhc2V0LzdfT25lQ2F0T25lTnVtLmNzdiIsIGhlYWRlcj1UUlVFLCBzZXA9IiwiKQoKIyBCYXJwbG90CmRhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYShWYWx1ZSkpICU+JQogIGFycmFuZ2UoVmFsdWUpICU+JQogIHRhaWwoMjApICU+JQogIG11dGF0ZShDb3VudHJ5PWZhY3RvcihDb3VudHJ5LCBDb3VudHJ5KSkgJT4lCiAgZ2dwbG90KCBhZXMoeD1Db3VudHJ5LCB5PVZhbHVlKSApICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgZmlsbD0iIzY5YjNhMiIpICsKICAgIGNvb3JkX2ZsaXAoKSArCiAgICB0aGVtZV9pcHN1bSgpICsKICAgIHRoZW1lKAogICAgICBwYW5lbC5ncmlkLm1pbm9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgbGVnZW5kLnBvc2l0aW9uPSJub25lIgogICAgKSArCiAgICB4bGFiKCIiKSArCiAgICB5bGFiKCJXZWFwb24gcXVhbnRpdHkgKFNJUFJJIHRyZW5kLWluZGljYXRvciB2YWx1ZSkiKQpgYGAKCkFub3RoZXIgdHlwZSBvZiBleGFtcGxlIGNhbiBiZSBmb3IgY3JlYXRpbmcgc3RhY2tlZCBiYXIgY2hhcnQuIFdlIHdpbGwgdXNlIE1QQUEgcmF0aW5nIHRvIGRpZmZlcmVudGlhdGUgbW92aWUgdHlwZSBhY2NvcmRpbmcgdG8gZ2VucmUuIAoKV2Ugd2lsbCB1c2UgdGhyZWUgTVBBQSByYXRpbmcgc3lzdGVtOiAKUiAtIFJlc3RyaWN0ZWQgKENvbnRhaW5zIHNvbWUgYWR1bHQgbWF0ZXJpYWwuIFBhcmVudHMgYXJlIHVyZ2VkIHRvIGxlYXJuIG1vcmUgYWJvdXQgdGhlIGZpbG0gYmVmb3JlIHRha2luZyB0aGVpciB5b3VuZyBjaGlsZHJlbiB3aXRoIHRoZW0uKQoKUEctMTMgLSBQYXJlbnRzIFN0cm9uZ2x5IENhdXRpb25lZCAoUGFyZW50cyBhcmUgdXJnZWQgdG8gYmUgY2F1dGlvdXMuIFNvbWUgbWF0ZXJpYWwgbWF5IGJlIGluYXBwcm9waWF0ZSBmb3IgcHJlLXRlZW5hZ2Vycy4pCgpQRyAtIFBhcmVudGFsIEd1aWRhbmNlIFN1Z2dlc3RlZCAoUGFyZW50cyB1cmdlZCB0byBnaXZlICJwYXJlbnRhbCBndWlkYW5jZS4iIE1heSBjb250YWluIHNvbWUgbWF0ZXJpYWwgcGFyZW50cyBtaWdodCBub3QgbGlrZSBmb3IgdGhlaXIgeW91bmcgY2hpbGRyZW4pCgpgYGB7cn0KIyBmb3IgcmVwcm9kdWNpYmlsaXR5CnNldC5zZWVkKDEyMykKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdnc3RhdHNwbG90KQoKIyBwbG90Cmdnc3RhdHNwbG90OjpnZ2JhcnN0YXRzKAogIGRhdGEgPSBnZ3N0YXRzcGxvdDo6bW92aWVzX2xvbmcsCiAgeCA9IG1wYWEsCiAgeSA9IGdlbnJlLAogIHNhbXBsaW5nLnBsYW4gPSAiam9pbnRNdWx0aSIsCiAgdGl0bGUgPSAiTVBBQSBSYXRpbmdzIGJ5IEdlbnJlIiwKICB4bGFiID0gIm1vdmllIGdlbnJlIiwKICBsZWdlbmQudGl0bGUgPSAiTVBBQSByYXRpbmciLAogIGdndGhlbWUgPSBocmJydGhlbWVzOjp0aGVtZV9pcHN1bSgpLAogIGdncGxvdC5jb21wb25lbnQgPSBsaXN0KHNjYWxlX3hfZGlzY3JldGUoZ3VpZGUgPSBndWlkZV9heGlzKG4uZG9kZ2UgPSAyKSkpLAogIHBhbGV0dGUgPSAiU2V0MiIsCiAgbWVzc2FnZXMgPSBGQUxTRQopCmBgYApTbywgZnJvbSBoZXJlIHdlIGNhbiBzYXkgdGhhdCBEcmFtYSBnZW5yZSBpcyBtb3JlIHJlc3RyaWN0ZWQgdGhhbiBhbnkgb3RoZXIgZ2VucmUuIAo6OjoKCjo6OnsjaGlzdG9ncmFtfQo6Ojp7I2NoYXJ0dGl0bGV9CioqSGlzdG9ncmFtKioKOjo6CkEgaGlzdG9ncmFtIGxvb2tzIGxpa2UgYSBiYXIgY2hhcnQsIGJ1dCBtZWFzdXJlcyBmcmVxdWVuY3kgcmF0aGVyIHRoYW4gdHJlbmRzIG92ZXIgdGltZS5JdCBpcyBhbiBhY2N1cmF0ZSBncmFwaGljYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhIG51bWVyaWMgdmFyaWFibGUuIEl0IHRha2VzIGFzIGlucHV0IG51bWVyaWMgdmFyaWFibGVzIG9ubHkuIFRoZSB2YXJpYWJsZSBpcyBjdXQgaW50byBzZXZlcmFsIGJpbnMsIGFuZCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9uIHBlciBiaW4gaXMgcmVwcmVzZW50ZWQgYnkgdGhlIGhlaWdodCBvZiB0aGUgYmFyLiBUaGUgeC1heGlzIG9mIGEgaGlzdG9ncmFtIGxpc3RzIHRoZSDigJxiaW5z4oCdIG9yIGludGVydmFscyBvZiB0aGUgdmFyaWFibGUsIGFuZCB0aGUgeS1heGlzIGlzIGZyZXF1ZW5jeSwgc28gZWFjaCBiYXIgcmVwcmVzZW50cyB0aGUgZnJlcXVlbmN5IG9mIHRoYXQgYmluLiBGb3IgZXhhbXBsZSwgeW91IGNvdWxkIG1lYXN1cmUgdGhlIGZyZXF1ZW5jaWVzIG9mIGVhY2ggYW5zd2VyIHRvIGEgc3VydmV5IHF1ZXN0aW9uLiBUaGUgYmlucyB3b3VsZCBiZSB0aGUgYW5zd2VyOiDigJx1bnNhdGlzZmFjdG9yeSzigJ0g4oCcbmV1dHJhbCzigJ0gYW5kIOKAnHNhdGlzZmFjdG9yeS7igJ0gVGhpcyB3b3VsZCB0ZWxsIHlvdSBob3cgbWFueSBwZW9wbGUgZ2F2ZSBlYWNoIGFuc3dlci4KCkhlcmUgaXMgYW4gZXhhbXBsZSBzaG93aW5nIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIG5pZ2h0IHByaWNlIG9mIFJibmIgYXBwYXJ0ZW1lbnRzIGluIHRoZSBzb3V0aCBvZiBGcmFuY2UuIFByaWNlIHJhbmdlIGlzIGRpdmlkZWQgcGVyIDEwIGV1cm9zIGludGVydmFsLiBGb3IgZXhhbXBsZSwgdGhlcmUgYXJlIHNsaWdodGx5IGxlc3MgdGhhbiA3NTAgYXBwYXJ0ZW1lbnRzIHdpdGggYSBuaWdodCBwcmljZSBiZXR3ZWVuIDEwMCBhbmQgMTEwIGV1cm9zLgoKYGBge3J9CiMgTGlicmFyaWVzCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGhyYnJ0aGVtZXMpCmxpYnJhcnkodmlyaWRpcykKCiMgTG9hZCBkYXRhc2V0IGZyb20gZ2l0aHViCmRhdGEgPC0gcmVhZC50YWJsZSgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2hvbHR6eS9kYXRhX3RvX3Zpei9tYXN0ZXIvRXhhbXBsZV9kYXRhc2V0LzFfT25lTnVtLmNzdiIsIGhlYWRlcj1UUlVFKQoKIyBNYWtlIHRoZSBoaXN0b2dyYW0KZGF0YSAlPiUKICBmaWx0ZXIoIHByaWNlPDMwMCApICU+JQogIGdncGxvdCggYWVzKHg9cHJpY2UpKSArCiAgICBzdGF0X2JpbihicmVha3M9c2VxKDAsMzAwLDEwKSwgZmlsbD0iIzY5YjNhMiIsIGNvbG9yPSIjZTllY2VmIiwgYWxwaGE9MC45KSArCiAgICBnZ3RpdGxlKCJOaWdodCBwcmljZSBkaXN0cmlidXRpb24gb2YgQWlyYm5iIGFwcGFydGVtZW50cyIpICsKICAgIHRoZW1lX2lwc3VtKCkKYGBgCgpUaGlzIGlzIGEgdmVyeSBiYXNpYyB5ZXQgdmVyeSBpbnNpZ2h0ZnVsIGV4YW1wbGUgb2YgaG93IGhpc3RvZ3JhbSBjYW4gZ2l2ZSBzdWNoIGluc2lnaHRzLiAKOjo6Cgo6Ojp7I3NjYXR0ZXJwbG90fQo6Ojp7I2NoYXJ0dGl0bGV9CioqU2NhdHRlciBQbG90KioKOjo6ClNjYXR0ZXIgcGxvdHMgYXJlIHVzZWQgdG8gZmluZCBjb3JyZWxhdGlvbnMuIEVhY2ggcG9pbnQgb24gYSBzY2F0dGVyIHBsb3QgbWVhbnMg4oCcd2hlbiB4ID0gdGhpcywgdGhlbiB5IGVxdWFscyB0aGlzLuKAnSBUaGF0IHdheSwgaWYgdGhlIHBvaW50cyB0cmVuZCBhIGNlcnRhaW4gd2F5ICh1cHdhcmQgdG8gdGhlIGxlZnQsIGRvd253YXJkIHRvIHRoZSByaWdodCwgZXRjLikgdGhlcmUgaXMgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGVtLiBJZiB0aGUgcGxvdCBpcyB0cnVseSBzY2F0dGVyZWQgd2l0aCBubyB0cmVuZCBhdCBhbGwsIHRoZW4gdGhlIHZhcmlhYmxlcyBkbyBub3QgYWZmZWN0IGVhY2ggb3RoZXIgYXQgYWxsLgoKRm9yIGV4YW1wbGUgd2Ugd2lsbCBzZWUgZXZvbHV0aW9uIG9mIGJpdGNvaW4gb24gYXByaWwgMjAxODoKCmBgYHtyfQojIExpYnJhcmllcwpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoaHJicnRoZW1lcykKCiMgTG9hZCBkYXRhc2V0IGZyb20gZ2l0aHViCmRhdGEgPC0gcmVhZC50YWJsZSgiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2hvbHR6eS9kYXRhX3RvX3Zpei9tYXN0ZXIvRXhhbXBsZV9kYXRhc2V0LzNfVHdvTnVtT3JkZXJlZC5jc3YiLCBoZWFkZXI9VCkKCmRhdGEkZGF0ZSA8LSBhcy5EYXRlKGRhdGEkZGF0ZSkKCiMgUGxvdApkYXRhICU+JQogIHRhaWwoMTApICU+JQogIGdncGxvdCggYWVzKHg9ZGF0ZSwgeT12YWx1ZSkpICsKICAgIGdlb21fbGluZSggY29sb3I9ImdyZXkiKSArCiAgICBnZW9tX3BvaW50KHNoYXBlPTIxLCBjb2xvcj0icmVkIiwgZmlsbD0iIzY5YjNhMiIsIHNpemU9NikgKwogICAgdGhlbWVfaXBzdW0oKSArCiAgICBnZ3RpdGxlKCJFdm9sdXRpb24gb2YgYml0Y29pbiBwcmljZSIpCmBgYAo6OjoKCjo6OnsjbWFwfQo6Ojp7I2NoYXJ0dGl0bGV9CioqTWFwKioKOjo6CmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9Cmluc3RhbGwucGFja2FnZXMoInNmIikKaW5zdGFsbC5wYWNrYWdlcygicmFzdGVyIikKaW5zdGFsbC5wYWNrYWdlcygic3BEYXRhIikKcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoIk5vd29zYWQvc3BEYXRhTGFyZ2UiKQpgYGAKCmBgYHtyLGVjaG89IEZBTFNFfQpsaWJyYXJ5KHNmKSAjIyBjbGFzc2VzIGFuZCBmdW5jdGlvbnMgZm9yIHZlY3RvciBkYXRhCmxpYnJhcnkocmFzdGVyKSAgICAgICMgY2xhc3NlcyBhbmQgZnVuY3Rpb25zIGZvciByYXN0ZXIgZGF0YQpsaWJyYXJ5KHNwRGF0YSkgICAgICAgICMgbG9hZCBnZW9ncmFwaGljIGRhdGEKbGlicmFyeShzcERhdGFMYXJnZSkgICAjIGxvYWQgbGFyZ2VyIGdlb2dyYXBoaWMgZGF0YQpgYGAKCmBgYHtyfQp2aWduZXR0ZShwYWNrYWdlID0gInNmIikgIyBzZWUgd2hpY2ggdmlnbmV0dGVzIGFyZSBhdmFpbGFibGUKdmlnbmV0dGUoInNmMSIpICAgICAgICAgICMgYW4gaW50cm9kdWN0aW9uIHRvIHRoZSBwYWNrYWdlCmBgYAoKYGBge3J9Cm5hbWVzKHdvcmxkKQpwbG90KHdvcmxkKQpgYGAKTWFraW5nIG1hcCB1c2luZyBSOgpgYGB7cixlY2hvPUZBTFNFfQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHJhc3RlcikKbGlicmFyeShkcGx5cikKbGlicmFyeShzcERhdGEpCmxpYnJhcnkoc3BEYXRhTGFyZ2UpCmxpYnJhcnkodG1hcCkgICAgIyBmb3Igc3RhdGljIGFuZCBpbnRlcmFjdGl2ZSBtYXBzCmxpYnJhcnkobGVhZmxldCkgIyBmb3IgaW50ZXJhY3RpdmUgbWFwcwpsaWJyYXJ5KGdncGxvdDIpICMgdGlkeXZlcnNlIGRhdGEgdmlzdWFsaXphdGlvbiBwYWNrYWdlCgptYXBfbnogPSB0bV9zaGFwZShueikgKyB0bV9wb2x5Z29ucygpCnRtYXBfbW9kZSgidmlldyIpCm1hcF9uegpgYGAKClNvIHRoZXNlIGFyZSBmZXcgZXhhbXBsZXMgb2YgdmlzdWFsaXppbmcgZGF0YS4gCjo6Og==